var ws = require('nodejs-websocket');
var port = 8099;

//进入房间
const SIGNAL_TYPE_JOIN = "join";
const SIGNAL_TYPE_RESP_JOIN = "resp-join"; //告之加入者对方是谁
const SIGNAL_TYPE_LEAVE = "leave";
const SIGNAL_TYPE_NEW_PEER = "new-peer";

const SIGNAL_TYPE_OFFER = "offer";
const SIGNAL_TYPE_ANSWER = "answer";
const SIGNAL_TYPE_CANDIDATE = "candidate";


var ZeroRTCMap = function () {
    this._entrys = new Array();

    this.put = function (key, value) {
        if (key == null || key == undefined) {
            return;
        }

        var index = this._getIndex(key);

        if (index == -1) {
            var entry = {
                key,
                value
            }
            this._entrys[this._entrys.length] = entry
        } else {
            this._entrys[index].value = value;
        }
    };

    this.get = function (key) {
        var index = this._getIndex(key);
        return index != -1 ? this._entrys[index].value : null
    }

    this.remove = function (key) {
        var index = this._getIndex(key);
        if (index != -1) {
            this._entrys.splice(index, 1);
        }
    }

    this.clear = function (key) {
        this._entrys.length = 0;
    }
    this.contains = function (key) {
        var index = this._getIndex(key);
        return index != -1;
    }

    this.size = function (key) {
        return this._entrys.length;
    }

    this.getEntrys = function () {
        return this._entrys;
    }


    this._getIndex = function (key) {
        if (key == null || key == undefined) {
            return -1;
        }

        var _length = this._entrys.length;

        for (var i = 0; i < _length; i++) {
            var entry = this._entrys[i];
            if (entry == null || entry == undefined) {
                continue;
            }

            if (entry.key === key) {
                return i;
            }
        }
        return -1;
    }


}

var roomTableMap = new ZeroRTCMap();

function Client(uid, conn, roomId) {
    this.uid = uid;
    this.conn = conn;
    this.roomId = roomId;
}

function handleLeave(msg, conn) {
    const { roomId, uid } = msg;

    var roomMap = roomTableMap.get(roomId);

    if (roomMap == null) {
        console.log("房间不存在:" + roomId);
        return;
    }

    //清除自己
    roomMap.remove(uid);

    //还有其它人
    if (roomMap.size() > 0) {
        var clients = roomMap.getEntrys();
        for (let index = 0; index < clients.length; index++) {

            const remoteUid = clients[index].key;


            var remoteClient = roomMap.get(remoteUid);

            if (remoteClient) {
                var msg = {
                    "cmd": SIGNAL_TYPE_LEAVE,
                    "remoteUid": uid //谁离开就填谁
                }
                console.log(`通知${remoteUid},现在${uid}离开了`);
                var json = JSON.stringify(msg);
                remoteClient.conn.sendText(json);
            }




        }
    }
}

function handleJoin(msg, conn) {
    const { roomId, uid } = msg;

    var roomMap = roomTableMap.get(roomId);

    if (roomMap == null) {
        roomMap = new ZeroRTCMap();

        roomTableMap.put(roomId, roomMap)
    }

    if (roomMap.size > 2) {
        console.log("roomId:" + roomId + "已经有两人存在,请使用其它房间")
        //加信息通告客户端
        return;
    }

    var client = new Client(uid, conn, roomId)

    roomMap.put(uid, client);

    console.log(roomMap, "=========roomMap=========");

    if (roomMap.size() > 1) {
        //房间已经有人了 ,加上新来的人 那就是>=2 所以要通知对方
        var clients = roomMap.getEntrys();

        for (let index = 0; index < clients.length; index++) {
            const item = clients[index];
            const client = item.value;
            var remoteUid = client.uid;
            if (remoteUid != uid) {
                var msg = {
                    "cmd": SIGNAL_TYPE_NEW_PEER,
                    "remoteUid": uid
                }

                var remoteClient = roomMap.get(remoteUid);
                var json = JSON.stringify(msg);
                remoteClient.conn.sendText(json);


                //已经已经有人  那么连上后 要将对方的uid告诉我
                var msg = {
                    "cmd": SIGNAL_TYPE_RESP_JOIN,
                    "remoteUid": remoteUid
                }
                var json = JSON.stringify(msg);
                conn.sendText(json);


            }
        }


    }



}


function handleOffer(msg, conn) {
    const { roomId, uid, remoteUid } = msg;

    var roomMap = roomTableMap.get(roomId);

    if (roomMap == null) {
        console.log("房间不存在", "===========handleOffer============");
        return;
    }

    //找人
    if (roomMap.get(uid) == null) {
        return;
    }

    var remoteClient = roomMap.get(remoteUid);
    if (remoteClient) {
        remoteClient.conn.sendText(JSON.stringify(msg))
    } else {
        console.log("remoteClient不存在", "===========handleOffer.remoteClient============");
    }

}

function handleAnswer(msg, conn) {
    const { roomId, uid, remoteUid } = msg;

    var roomMap = roomTableMap.get(roomId);

    if (roomMap == null) {
        console.log("房间不存在", "===========handleAnswer============");
        return;
    }

    //找人
    if (roomMap.get(uid) == null) {
        return;
    }

    var remoteClient = roomMap.get(remoteUid);
    if (remoteClient) {
        remoteClient.conn.sendText(JSON.stringify(msg))
    } else {
        console.log("remoteClient不存在", "===========handleAnswer.remoteClient============");
    }

}


function handleCandidate(msg, conn) {
    const { roomId, uid, remoteUid } = msg;

    var roomMap = roomTableMap.get(roomId);

    if (roomMap == null) {
        console.log("房间不存在", "===========handleCandidate============");
        return;
    }

    //找人
    if (roomMap.get(uid) == null) {
        return;
    }

    var remoteClient = roomMap.get(remoteUid);
    if (remoteClient) {
        remoteClient.conn.sendText(JSON.stringify(msg))
    } else {
        console.log("remoteClient不存在", "===========handleCandidate.remoteClient============");
    }

}

var server = ws.createServer(function (conn) {
    console.log("=====创建一个新链接======");

    conn.on('text', function (json) {
        console.log("收到信息:" + json);


        var msg = JSON.parse(json);

        switch (msg.cmd) {
            case SIGNAL_TYPE_JOIN:
                handleJoin(msg, conn)
                break;
            case SIGNAL_TYPE_LEAVE:
                handleLeave(msg, conn)
                break;

            case SIGNAL_TYPE_OFFER:
                handleOffer(msg, conn)
                break;
            case SIGNAL_TYPE_ANSWER:
                handleAnswer(msg, conn)
                break;

            case SIGNAL_TYPE_CANDIDATE:
                handleCandidate(msg, conn)
                break;
        }

    })

    conn.on('close', function (code, reason) {
        console.log(code, reason, "连接关闭");

    })

    conn.on('error', function (err) {
        console.log(err, "========error=========");
    })

}).listen(port)
